package com.atom.module.mvvm.base.view.activity

import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.view.KeyEvent
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import com.atom.module.mvvm.base.viewmodel.AbstractBaseContainerViewModel
import com.atom.module.mvvm.base.ApiActivity
import com.atom.module.mvvm.base.ApiFragment

abstract class AbstractBaseContainerMVVMActivity<V : ViewDataBinding, VM : AbstractBaseContainerViewModel<*>> :
    AbstractBaseMVVMActivity<V, VM>(), ApiActivity {

    abstract fun initContainerView(): Int

    override fun loadFragment(
        fragment: Fragment,
        addToBackStack: Boolean
    ) {
        val fragmentManager = supportFragmentManager
        val fragmentTransaction =
            fragmentManager.beginTransaction()
        val fragmentById =
            fragmentManager.findFragmentById(initContainerView())
        if (fragmentById == null) {
            fragmentTransaction.add(initContainerView(), fragment, fragment.javaClass.name)
        } else {
            if (fragmentById.javaClass == fragment.javaClass) {
                if (fragmentById is ApiFragment.OnNewIntentListener) {
                    if (fragmentById.onNewIntent(fragment.arguments)) {
                        return
                    }
                }
            }
            fragmentTransaction.replace(initContainerView(), fragment, fragment.javaClass.name)
        }
        if (addToBackStack) {
            fragmentTransaction.addToBackStack(fragment.javaClass.name)
        }
        fragmentTransaction.commit()
    }

    override fun loadFragment(
        fragmentClass: Class<out Fragment>,
        addToBackStack: Boolean,
        bundle: Bundle?
    ) {
        loadFragment(
            supportFragmentManager.fragmentFactory.instantiate(
                this.classLoader,
                fragmentClass.canonicalName
            ).also {
                it.arguments = bundle
            }, addToBackStack
        )
    }

    override fun changeFragment(
        newFragment: Fragment,
        oldFragment: Fragment?
    ) {
        val fragmentManager = supportFragmentManager
        val fragmentTransaction = fragmentManager.beginTransaction()
        oldFragment?.also { fragmentTransaction.detach(it) }  // 从界面移除，但是还在Fragment的缓存空间中
        if (newFragment.isDetached) {
            fragmentTransaction.attach(newFragment)
        }
        fragmentTransaction.commit()  // 提交事务
    }

    override fun onBackPressed() {
        val fragmentManager = supportFragmentManager
        var fragment = fragmentManager.findFragmentById(initContainerView())
        if (fragment is ApiFragment.OnBackPressedListener) {
            if (fragment.onBackPressed()) {
                return
            }
        }
        super.onBackPressed()
        fragment = fragmentManager.findFragmentById(initContainerView())
        if (fragment == null) {
            finish()
        }
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        val fragmentManager = supportFragmentManager
        val fragment = fragmentManager.findFragmentById(initContainerView())
        if (fragment is ApiFragment.OnKeyPressedListener) {
            if (fragment.onKeyDown(keyCode, event)) {
                return true
            }
        }
        if (fragment is ApiFragment.OnMenuPressedListener) {
            if (keyCode == KeyEvent.KEYCODE_MENU) {
                if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ECLAIR) {
                    event.startTracking()
                } else {
                    fragment.onMenuPressed()
                }
                return true
            }
        }
        return super.onKeyDown(keyCode, event)
    }

    override fun onKeyLongPress(keyCode: Int, event: KeyEvent?): Boolean {
        val fragmentManager = supportFragmentManager
        val fragment =
            fragmentManager.findFragmentById(initContainerView())
        if (fragment is ApiFragment.OnKeyPressedListener) {
            if (fragment.onKeyLongPress(keyCode, event)) {
                return true
            }
        }
        return super.onKeyLongPress(keyCode, event)
    }

    override fun onKeyMultiple(
        keyCode: Int,
        count: Int,
        event: KeyEvent?
    ): Boolean {
        val fragmentManager = supportFragmentManager
        val fragment =
            fragmentManager.findFragmentById(initContainerView())
        if (fragment is ApiFragment.OnKeyPressedListener) {
            if (fragment.onKeyMultiple(keyCode, count, event)) {
                return true
            }
        }
        return super.onKeyMultiple(keyCode, count, event)
    }

    override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
        val fragmentManager = supportFragmentManager
        val fragment =
            fragmentManager.findFragmentById(initContainerView())
        if (fragment is ApiFragment.OnKeyPressedListener) {
            if (fragment.onKeyUp(keyCode, event)) {
                return true
            }
        }
        if (fragment is ApiFragment.OnMenuPressedListener) {
            if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ECLAIR) {
                if (keyCode == KeyEvent.KEYCODE_MENU && event.isTracking && !event.isCanceled) {
                    fragment.onMenuPressed()
                    return true
                }
            }
        }
        return super.onKeyUp(keyCode, event)
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        val fragmentManager = supportFragmentManager
        var fragment =
            fragmentManager.findFragmentById(initContainerView())
        if (fragment is ApiFragment.OnNewIntentListener) {
            if (fragment.onNewIntent(intent.extras)) {
                return
            }
        }
        val classname =
            intent.getStringExtra(AbstractBaseContainerViewModel.ParameterField.EXTRA_FRAGMENT_CLASS_NAME)
        if (classname != null) {
            try {
                val clazz = classLoader.loadClass(classname)
                fragment = clazz.newInstance() as Fragment
                fragment.arguments = intent.extras
                loadFragment(fragment, true)
            } catch (e: Exception) {
                // TODO add e handle
            }
        }
    }

    override fun finish() {
        val fragmentManager = supportFragmentManager
        val fragment =
            fragmentManager.findFragmentById(initContainerView())
        if (fragment is ApiFragment.OnFinishListener) {
            if (fragment.onFinish()) {
                return
            }
        }
        super.finish()
    }

}
